/**
 @file Announce_Handler.cpp

 Periodically sending announcing packets when a service is registered

 @author Kyoungho An <kyoungho.an@gmail.com>
*/

#ifndef _ANNOUNCE_HANDLER_CPP_
#define _ANNOUNCE_HANDLER_CPP_

#include "Announce_Handler.h"

using namespace MDNS;

Announce_Handler::Announce_Handler (ACE_Reactor *r)
: ACE_Event_Handler (r)
{
	ACE_DEBUG ((LM_DEBUG, "Announce_Handler constructor\n"));
}

int Announce_Handler::open (struct mdnsd *svr)
{
	ACE_DEBUG ((LM_DEBUG, "Announce_Handler::init \n"));
	// initialize MDNS daemon object
	this->svr_ = svr;

	// allocate memory for replying packet
	this->mdns_reply_ = (struct mdns_pkt *) malloc (sizeof(struct mdns_pkt));
	memset (this->mdns_reply_, 0, sizeof(struct mdns_pkt));

	// open multicast connection
	mcast_addr_.set (MDNS_PORT, MDNS_ADDR);
	mcast_dgram_.join (mcast_addr_);

	// set interval value to 1 second
	ACE_Time_Value initial_delay (0);
	ACE_Time_Value interval (1);

	// schedule timeout handler
	this->reactor ()->schedule_timer (this, 0, initial_delay, interval);

	return 0;
}

int Announce_Handler::handle_timeout (const ACE_Time_Value &current_time, 
	const void *act)
{
	// print out the current time
	time_t epoch = ((timespec_t)current_time).tv_sec;
	ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handle_timeout: %s\n"), ACE_OS::ctime
		(&epoch)));

	struct rr_entry *ann_e = NULL;

	// get announce entry from the MDNS daemon
	if (this->svr_->announce)
		ann_e = rr_list_remove (&(this->svr_->announce), this->svr_->announce->e);

	// if there is no announce entry, return 0
	if (! ann_e)
		return 0;

	// make up and store announcing packet to the replying packet
	announce_srv (this->svr_, this->mdns_reply_, ann_e->name);

	if (this->mdns_reply_->num_ans_rr > 0) {
		// encode and send the replying packet
		size_t replylen = mdns_encode_pkt (this->mdns_reply_, this->pkt_buf_,
			BUFFER_SIZE);
		mcast_dgram_.send (this->pkt_buf_, replylen);
	}
	
	return 0;
}

int Announce_Handler::handle_close (ACE_HANDLE) 
{
	// delete allocated memory
	if (this->svr_)
		free (this->svr_);
	if (this->mdns_reply_)
		free (this->mdns_reply_);
	this->mcast_dgram_.leave (this->mcast_addr_);
	return 0;
}

#endif
